package com.chris.cc.user.service.impl;

import com.chris.cc.common.exception.InvalidArgumentException;
import com.chris.cc.user.mapper.PermittedRoleMapper;
import com.chris.cc.user.mapper.RoleMapper;
import com.chris.cc.user.mapper.UserRoleMapper;
import com.chris.cc.user.model.dto.RoleDto;
import com.chris.cc.user.model.entity.PermittedRole;
import com.chris.cc.user.model.entity.Role;
import com.chris.cc.user.model.entity.UserRole;
import com.chris.cc.user.service.RoleService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.*;

/**
 * Copyright (c) 2018-2025, chris All rights reserved.
 * <p>
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * <p>
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * <p>
 * Author: haoka (haokang207@126.com)
 * <p>
 * Date: 2018/8/24 10:05
 **/
@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private PermittedRoleMapper permittedRoleMapper;

    @Override
    public Role add(RoleDto role) throws InvalidArgumentException {
        Role u = Role.builder()
                .roleId(role.getRoleId())
                .code(role.getCode())
                .name(role.getName())
                .description(role.getDescription())
                .enable(role.getEnable())
                .build();
        u.setModifyDate(new Date());
        u.setCreateDate(new Date());
        try {
            roleMapper.insert(u);
        } catch (DuplicateKeyException e) {
            throw new InvalidArgumentException("代码已存在", role.getCode());
        }
        return u;
    }

    @Override
    public Page<Role> query(Long userId, Boolean enable, String keyword, Pageable page) {
        //不支持sort
        List<Role> list = roleMapper.select4User(userId, enable, keyword, page.getOffset(), page.getPageSize());
        int total = roleMapper.selectCount4User(userId, enable, keyword);
        return new PageImpl<>(list, page, total);
    }

    @Override
    public Role toggle(Long roleId, Boolean enable) {
        if (roleId == null || enable == null) {
            return null;
        }
        Role u = Role.builder()
                .roleId(roleId)
                .enable(enable)
                .build();
        u.setModifyDate(new Date());
        roleMapper.updateByPrimaryKeySelective(u);
        return roleMapper.selectByPrimaryKey(roleId);
    }

    @Override
    public Role update(RoleDto role) throws InvalidArgumentException {
        if (role.getRoleId() == null) {
            return null;
        }
        Role u = Role.builder()
                .roleId(role.getRoleId())
                .name(role.getName())
                .code(role.getCode())
                .description(role.getDescription())
                .enable(role.getEnable())
                .build();
        u.setModifyDate(new Date());
        try {
            roleMapper.updateByPrimaryKeySelective(u);
        } catch (DuplicateKeyException e) {
            throw new InvalidArgumentException("名称或代码已存在", e.getMessage());
        }
        return roleMapper.selectByPrimaryKey(role.getRoleId());
    }

    @Override
    public List<Role> getByCode(String... code) {
        if (code == null || code.length == 0) {
            return Collections.emptyList();
        }
        Set<String> codes = new HashSet<>();
        for (String c : code) {
            if (StringUtils.isNotBlank(c)) {
                codes.add(c.trim());
            }
        }
        if (codes.isEmpty()) {
            return Collections.emptyList();
        }
        Example e = new Example(Role.class);
        e.createCriteria().andIn("code", codes);
        return roleMapper.selectByExample(e);
    }

    @Override
    public List<Role> getByUserId(Long userId) {
        if (userId == null) {
            return Collections.emptyList();
        }
        return userRoleMapper.selectRoleByUserId(userId);
    }

    @Override
    public List<Role> getPermittedRolesByUserId(Long userId) {
        if (userId == null) {
            return Collections.emptyList();
        }
        return permittedRoleMapper.selectRoleByUserId(userId);
    }

    @Override
    public Role getById(Long id) {
        if (id == null) {
            return null;
        }
        return roleMapper.selectByPrimaryKey(id);
    }

    /**
     * 获取角色可授予的角色列表
     *
     * @param roleId
     * @return
     */
    @Override
    public List<Role> getPermittedRolesByRoleId(Long roleId) {
        if (roleId == null) {
            return Collections.emptyList();
        }
        return permittedRoleMapper.selectRoleByRoleId(roleId);
    }

    /**
     * 更新可授予角色列表
     *
     * @param roleId
     * @param ids
     */
    @Override
    public void updatePermitRole(Long roleId, Long[] ids) {
        Example e = new Example(PermittedRole.class);
        e.createCriteria().andEqualTo("roleId", roleId);
        permittedRoleMapper.deleteByExample(e);
        for (Long id : ids) {
            PermittedRole permittedRole = PermittedRole.builder().permittedRoleId(id).roleId(roleId).build();
            permittedRole.setCreateDate(new Date());
            permittedRoleMapper.insert(permittedRole);
        }
    }

    /**
     * 更新用户的角色
     *
     * @param userId
     * @param roleIds
     */
    @Override
    public void updateUserRole(Long userId, Long... roleIds) {
        Example e = new Example(UserRole.class);
        e.createCriteria().andEqualTo("userId", userId);
        userRoleMapper.deleteByExample(e);
        for (Long id : roleIds) {
            UserRole userRole = UserRole.builder().userId(userId).roleId(id).build();
            userRole.setCreateDate(new Date());
            userRoleMapper.insert(userRole);
        }
    }
}
